﻿//思路是：（准心的是进行猜测）
 // 
 //消息处理进行
 // 
 //创建一个窗体，再写入代码，进行编写气球，(气球是编写一个结构体，结构体里面有
 //基本数据，这个基本数据是(原点位置，半径，颜色),进行随机读写，当气球飞出去的
 //时候，需要进行删除操作，进行完删除操作后，再进行再次初始化气球。
 //进行准心的创建，在准心的创建中，我们要进行准心的位置要在气球的里面(将气球的
 //原点与准心的原点进行距离公式，在点击鼠标后，进行删除气球操作，后紧接着运用加
 //入气球操作。要判断鼠标点击的位置与圆心之间的位置是否大于半径。)

#define WIDOWN_HEIGHT 800     //窗体的高度
#define WIDOWN_WIDTH 600      //窗体的宽度
#define MAX_IN_WIDOWN 5       //在窗体范围中出现的气球数量
#define BALLOON_RADIUS 30     //气球的半径

#include <stdio.h>
#include <easyx.h>
#include <math.h>
//进行气球结构体的创建
typedef struct {
	int x;             //气球的原点坐标的x值
	int y;             //气球的原点坐标的y值
	int r;             //气球的半径大小
	int v;             //气球的速度大小
	COLORREF color;    //气球的颜色，类型是COLORREF,要记住
}balloon;
//定义这个气球数组
balloon arrballoons[MAX_IN_WIDOWN];
//创建气球函数
balloon createballoon()
{
	balloon b;
	int m, n;
	m = 100;
	n = 700;
	b.x = rand() % (n - m + 1) + m;
	b.y = WIDOWN_HEIGHT;
	m = 1;
	n = 3;
	b.v = rand() % (n - m + 1) + m;
	b.r = BALLOON_RADIUS;
	b.color = RGB(rand() % 256, rand() % 256, rand() % 256);
	return b;
}

int main()
{
	//创建一个窗体
	initgraph(WIDOWN_HEIGHT, WIDOWN_WIDTH);
	setbkcolor(WHITE);
	cleardevice();
    //用来记录当前画面中还存在多少气球数量
	int count = MAX_IN_WIDOWN;  
    //用来存放准心的x,y坐标
	int MouseX = 0, MouseY = 0;
	//初始化气球
	for (int i = 0; i < MAX_IN_WIDOWN; i++)
	{
		arrballoons[i] = createballoon();
	}
    //利用高精帧率控制画面
	timeBeginPeriod(1);
	LARGE_INTEGER startCount, endCount, F;
	QueryPerformanceFrequency(&F);
	BeginBatchDraw();

	while (1)//主循环
	{
		//获取开始的时间
		QueryPerformanceCounter(&startCount);
	    //绘制画面
		cleardevice();
		for (int i = 0; i < MAX_IN_WIDOWN; i++)
		{
			setfillcolor(arrballoons[i].color);
			solidcircle(arrballoons[i].x, arrballoons[i].y, arrballoons[i].r);
		}
		//控制气球的速度
		for (int i = 0; i < MAX_IN_WIDOWN; i++)
		{
			arrballoons[i].y -= arrballoons[i].v;
		}
		//利用循环进行删除气球
		int i = 0;
		while (i < count)
		{
			if (arrballoons[i].y < -BALLOON_RADIUS)
			{
				for (int j = i; j < count - 1; j++)
					arrballoons[j] = arrballoons[j + 1];
				count--;
			}
			else
			{
				i++;
			}
		}
		//利用循环进行加入气球
		if (count < MAX_IN_WIDOWN)
		{
			arrballoons[count] = createballoon();
			count++;
		}
		//准心的初始化
		setlinecolor(RGB(199, 77, 130));
		setlinestyle(PS_SOLID, 3);
		circle(MouseX, MouseY, 20);
		line(MouseX - 20, MouseY, MouseX + 20, MouseY);
		line(MouseX, MouseY + 20, MouseX, MouseY - 20);

		QueryPerformanceCounter(&endCount);
		long long elapse = (endCount.QuadPart - startCount.QuadPart) * 1000000 / F.QuadPart;

		while (elapse < 1000000 / 100) 
		{
			Sleep(1);
			//建立锚点，因为如果建立在外面，那么我们鼠标会有延迟，所以需要进行多次更新鼠标位置
			ExMessage msg;
			//getmessage(&msg, EX_MOUSE);  //阻塞函数,会将程序中的代码进行阻塞，无法完成进行中的操作
			bool IsOK = peekmessage(&msg, EX_MOUSE);  //getmessage和peekmessage函数的功能大致相同
			//如果他接收到了这个鼠标消息，那么返回true，如果没接收到，就返回false
			if (IsOK == true)
			{
				//消息处理，如果接触到的是鼠标滑动的信息
				if (msg.message == WM_MOUSEMOVE)
				{
					MouseX = msg.x;
					MouseY = msg.y;
				}
	            //消息处理，如果接触到的是鼠标点击的信息
				else if (msg.message == WM_LBUTTONDOWN)
				{
					int i = 0;
					while (i < count)
					{
						int ballx = arrballoons[i].x;
						int bally = arrballoons[i].y;
						int distance = (int)sqrt((ballx - MouseX) * (ballx - MouseX) + (bally - MouseY) * (bally - MouseY));
						//删除气球的条件
						if (distance < BALLOON_RADIUS)
						{
							for (int j = i; j < count; j++)
								arrballoons[j] = arrballoons[j + 1];
							count--;
						}
						else
						{
							i++;
						}
					}
				}
			}
			QueryPerformanceCounter(&endCount);
			elapse = (endCount.QuadPart - startCount.QuadPart) * 1000000 / F.QuadPart;
		}
		FlushBatchDraw();
	}
	EndBatchDraw();
	timeEndPeriod(1);//这个是和timeBeginPeriod是成对出现的
	getchar();
	closegraph();
	return 0;
}
